package com.ruoyi.file.service;

import com.ruoyi.file.config.MinioConfig;
import com.ruoyi.file.utils.FileUploadUtils;
import io.minio.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * Minio 文件存储
 *
 * @author ruoyi
 */
@Service
public class MinioSysFileServiceImpl implements ISysFileService {
    @Autowired
    private MinioConfig minioConfig;

    @Autowired
    private MinioClient client;

    /**
     * Minio文件上传接口
     *
     * @param file 上传的文件
     * @return 访问地址
     * @throws Exception
     */
    @Override
    public String uploadFile(MultipartFile file) throws Exception {
        String fileName = StringtoMD5(FileUploadUtils.extractFilename(file));
        InputStream inputStream = file.getInputStream();
        PutObjectArgs args = PutObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(fileName + "." + getFileExtension(file))
                .stream(inputStream, file.getSize(), -1)
                .contentType(file.getContentType())
                .build();
        client.putObject(args);
        return "/" + minioConfig.getBucketName() + "/" + fileName + "." + getFileExtension(file);
    }

    @Override
    public String uploadGetPath(MultipartFile file) throws Exception {
        String fileName = StringtoMD5(FileUploadUtils.extractFilename(file));
        InputStream inputStream = file.getInputStream();
        PutObjectArgs args = PutObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(fileName + "." + getFileExtension(file))
                .stream(inputStream, file.getSize(), -1)
                .contentType(file.getContentType())
                .build();
        client.putObject(args);
        return "/" + minioConfig.getBucketName() + "/" + fileName + "." + getFileExtension(file);
    }

    @Override
    public String uploadFileBase64(String base64Image, String contentType, String fileName) throws Exception {
        byte[] imageBytes = Base64.getDecoder().decode(base64Image);
        String fileMd5Name = StringtoMD5(fileName);
        String ex = fileName.substring(fileName.lastIndexOf(".") + 1);
        // 创建输入流
        ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
        PutObjectArgs args = PutObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(fileMd5Name + "." + ex)
                .stream(inputStream, imageBytes.length, -1)
                .contentType(contentType)
                .build();
        // 上传对象到MinIO服务器
        client.putObject(args);
        return "/" + minioConfig.getBucketName() + "/" + fileMd5Name + "." + ex;
    }


    public String StringtoMD5(String content) {
        try {
            // 1. 创建MessageDigest实例，并指定"MD5"为算法参数
            MessageDigest md = MessageDigest.getInstance("MD5");

            // 2. 更新MessageDigest实例，输入需要转换为MD5的原始数据
            byte[] inputBytes = content.getBytes();
            md.update(inputBytes);

            // 3. 完成MessageDigest实例的更新后，调用digest方法计算MD5值
            byte[] hashBytes = md.digest();

            // 4. 将MD5值转换为16进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : hashBytes) {
                sb.append(String.format("%02x", b));
            }
            String md5Hash = sb.toString();

            // 输出MD5哈希值
            return md5Hash;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return content;
    }

    private String getFileExtension(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if (originalFilename != null && originalFilename.contains(".")) {
            return originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        }
        return null; // 或者返回一个默认值，表示没有后缀
    }

    /**
     *	下载文件
     * @param downloadFileName 将要从minio的桶中下载的文件名
     */
    public byte[] download(String downloadFileName) {

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        // 3.下载文件
        try {
            downloadFileName = downloadFileName.replaceAll(minioConfig.getBucketName(), "").replaceAll("/","");
            GetObjectArgs args = GetObjectArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .object(downloadFileName)
                    .build();
            GetObjectResponse object = client.getObject(args);

            byte buf[] = new byte[1024];
            int length = 0;

            // 输出文件
            while ((length = object.read(buf)) > 0) {
                outputStream.write(buf, 0, length);
            }
            // 关闭输出流

            byte[] byteArray = outputStream.toByteArray();
            return byteArray;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("下载失败!");
        }finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }

    @Override
    public String getMinioUrl() {
        return minioConfig.getUrl();
    }


}
